package edu.chl.grupp11.aegas.controller.imp;

import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Observable;

import javax.swing.JLabel;
import javax.swing.JPanel;

import edu.chl.grupp11.aegas.constants.FileTypesConst;
import edu.chl.grupp11.aegas.controller.FileControllerFactory;
import edu.chl.grupp11.aegas.controller.IFileController;
import edu.chl.grupp11.aegas.controller.ITagController;
import edu.chl.grupp11.aegas.controller.IUpdateGUIController;
import edu.chl.grupp11.aegas.controller.TagControllerFactory;
import edu.chl.grupp11.aegas.model.AbstractConfig;
import edu.chl.grupp11.aegas.model.ConfigFactory;
import edu.chl.grupp11.aegas.utils.VerticalLayout;
import edu.chl.grupp11.aegas.view.FileView;
import edu.chl.grupp11.aegas.view.TagView;

public class UpdateGUIController implements IUpdateGUIController {
	private JPanel fileList;
	private JPanel filePanel;
	private JPanel tagList;
	private JPanel editPanel;
	private HashMap<String, FileView> files;
	private ArrayList<JPanel> panelList;
	private ITagController tagController;
	IFileController fileController;

	public UpdateGUIController(JPanel editPanel, JPanel filePanel,
			JPanel fileList, JPanel tagList) {
		this.editPanel = editPanel;
		this.filePanel = filePanel;
		this.fileList = fileList;
		this.tagList = tagList;
		panelList = new ArrayList<JPanel>();
		fileList.setLayout(new VerticalLayout());
		setPanels();

		tagController = TagControllerFactory.getTagController();
		fileController = FileControllerFactory.getFileController();
	}

	private void addTag(ArrayList<TagView> allTags, TagView tv) {
		TagView compareTag = TagView.getTagWithSameName(allTags, tv);
		if (compareTag != null) {
			if (!TagView.sameValue(compareTag, tv)) {
				compareTag.setTemporaryText("[DIFFERENT VALUES]");
			}
		} else {
			allTags.add(tv);
		}
	}

	private boolean isInPanel(FileView fv) {
		for (int i = 0; i < panelList.size(); i++) {
			for (int k = 0; k < panelList.get(i).getComponentCount(); k++) {
				if (panelList.get(i).getComponent(k).getClass() == FileView.class) {
					FileView temp2 = (FileView) panelList.get(i)
							.getComponent(k);
					if (temp2.getFile().getAbsolutePath()
							.equals(fv.getFile().getAbsolutePath())) {
						return true;
					}
				}
			}
		}
		return false;
	}

	private void removeFilesFromPanel() {
		for (int i = 0; i < panelList.size(); i++) {
			for (int k = 0; k < panelList.get(i).getComponentCount(); k++) {
				if ((panelList.get(i).getComponent(k).getClass() == FileView.class)) {
					FileView temp = (FileView) panelList.get(i).getComponent(k);
					if (files.containsValue(temp) == false) {
						panelList.get(i).remove(k);
					}
				}
			}
		}
	}

	private void setPanels() {
		for (int i = 0; i < FileTypesConst.ALL_FILE_FILTER.getExtensions().length; i++) {
			JPanel panel = new JPanel();
			panel.setName(FileTypesConst.ALL_FILE_FILTER.getExtensions()[i]);
			panel.setLayout(new VerticalLayout());
			final JLabel label = new JLabel(
					FileTypesConst.ALL_FILE_FILTER.getExtensions()[i]
							.toUpperCase());
			panel.add(label);
			panel.setBackground(new Color(219, 219, 220));
			panelList.add(panel);

			panel.addMouseListener(new MouseAdapter() {

				@Override
				public void mousePressed(MouseEvent me) {
					if (me.getButton() == 1) {
						boolean allSelected = true;
						for (FileView fv : files.values()) {
							if (label.getText().equalsIgnoreCase(
									fv.getFileType())) {
								if (!fv.isSelected()) {
									allSelected = false;
								}
							}
						}
						FileView lastFileView = null;
						for (FileView fv : files.values()) {
							if (label.getText().equalsIgnoreCase(
									fv.getFileType())) {
								fv.setSelected(!allSelected);
								lastFileView = fv;
							}
						}
						fileController.deselectFilesOfWrongType(lastFileView);
					}
				}
			});
		}
	}

	@Override
	public void update(Observable o, Object arg) {
		updateFileListGUI();
		updateEditPanelGUI();
	}

	private void updateEditPanelGUI() {
		tagList.removeAll();
		tagList.setLayout(new VerticalLayout());

		ArrayList<FileView> selectedFiles = fileController.getSelectedFiles();

		ArrayList<TagView> allTags = new ArrayList<TagView>();
		for (FileView fv : selectedFiles) {
			for (TagView tagView : tagController.getTagViews(fv.getFile())) {
				tagView.getIMetaTag().addObserver(tagView);
				addTag(allTags, tagView);
			}

			for (TagView tag : allTags) {
				tagList.add(tag);
				tagController.addTagView(tag);
			}
		}
		editPanel.repaint();
		editPanel.revalidate();
	}

	private void updateFileListGUI() {
		files = fileController.getFiles();
		if (files.isEmpty()) {
			panelList.clear();
			setPanels();
			fileList.removeAll();
			fileList.revalidate();
			fileList.repaint();
			filePanel.revalidate();
			filePanel.repaint();
			return;
		}

		updatePanels();

		filePanel.repaint();
		filePanel.revalidate();
	}

	private void updatePanels() {
		Iterator<FileView> temp = files.values().iterator();
		while (temp.hasNext()) {
			FileView fv = temp.next();
			AbstractConfig config = ConfigFactory.getSharedConfig();
			config.addObserver(fv);
			for (JPanel p : panelList) {
				if (p.getComponentCount() < 2) {
					if (fv.getFileType().equalsIgnoreCase((p.getName()))) {
						p.add(fv);
					}
					fileList.add(p);
				} else {
					for (int k = 0; k < p.getComponentCount(); k++) {
						if (p.getComponent(k).getClass() == FileView.class) {
							if (!isInPanel(fv)) {
								for (JPanel panel : panelList) {
									if (fv.getFileType().equalsIgnoreCase(
											(panel.getName()))) {
										panel.add(fv);
									}
									fileList.add(panel);
								}
							}
						}
					}
				}
			}
		}
		removeFilesFromPanel();
		for (JPanel panel : panelList) {
			if (panel.getComponentCount() < 2) {
				fileList.remove(panel);
			}
		}
	}
}
